/*
 * Copyright (c) 2025 CAX Conversion Project
 */
package com.comac.ins.cax.service.impl;

import cn.hutool.core.util.IdUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.comac.ins.cax.domain.CaxConvertInfo;
import com.comac.ins.cax.domain.CaxFileInfo;
import com.comac.ins.cax.domain.bo.CaxConvertInfoBo;
import com.comac.ins.cax.domain.vo.CaxConvertInfoExportVo;
import com.comac.ins.cax.domain.vo.CaxConvertInfoVo;
import com.comac.ins.cax.domain.vo.CaxConvertStatisticItem;
import com.comac.ins.cax.domain.vo.CaxConvertStatisticVo;
import com.comac.ins.cax.enums.CaxConstants;
import com.comac.ins.cax.enums.CaxConvertStatus;
import com.comac.ins.cax.enums.CaxConvertType;
import com.comac.ins.cax.mapper.CaxConvertInfoMapper;
import com.comac.ins.cax.mapper.CaxFileInfoMapper;
import com.comac.ins.cax.service.ICaxConvertInfoService;
import com.comac.ins.cax.service.ICaxQualityCheckerService;
import com.comac.ins.cax.utils.CaxFileConvertUtil;
import com.comac.ins.cax.utils.FileUtils;
import com.comac.ins.common.core.domain.model.LoginUser;
import com.comac.ins.common.core.exception.base.BaseException;
import com.comac.ins.common.core.utils.BizAssertUtil;
import com.comac.ins.common.core.utils.DateUtils;
import com.comac.ins.common.core.utils.ServletUtils;
import com.comac.ins.common.core.utils.StringUtils;
import com.comac.ins.common.excel.utils.ExcelUtil;
import com.comac.ins.common.mybatis.core.page.PageQuery;
import com.comac.ins.common.mybatis.core.page.TableDataInfo;
import com.comac.ins.common.satoken.utils.LoginHelper;
import com.comac.ins.system.domain.vo.SysClientVo;
import com.comac.ins.system.domain.vo.SysDictTypeVo;
import com.comac.ins.system.service.ISysClientService;
import com.comac.ins.system.service.ISysDictTypeService;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @author yk
 * @desc 转换Service
 * @date 2024-06-18 16:51
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class CaxConvertInfoServiceImpl implements ICaxConvertInfoService {
    private static final String UPLOAD_PATH = "/data/file/convert/";

    @Autowired
    private CaxConvertInfoMapper caxConvertInfoMapper;

    @Autowired
    private ISysClientService sysClientService;

    @Autowired
    private ICaxQualityCheckerService iCaxQualityCheckerService;

    @Autowired
    private CaxFileInfoMapper caxFileInfoMapper;

    private final ISysDictTypeService sysDictTypeService;

    @Override
    public CaxConvertInfoVo convert(MultipartFile file, Long sourceFileId, String fileSourceType, String convertTypeStr,
                                    String inputTypeStr, String outputTypeStr) {
        // 获取用户来源
        String clientId = ServletUtils.getRequest().getHeader(LoginHelper.CLIENT_KEY);
        SysClientVo sysClientVo = sysClientService.queryByClientId(clientId);
        CaxConvertType caxConvertType = CaxConvertType.valueOf(convertTypeStr);
        Assert.notNull(caxConvertType, "conversionType字段非法");

        // 将文件保存到服务器
        String sourceFilePath;
        String fileName;
        if (CaxConstants.FILE_SOURCE_TYPE_SYS.equals(fileSourceType)) {
            //系统文件
            CaxFileInfo caxFileInfo = caxFileInfoMapper.selectById(sourceFileId);
            Assert.notNull(caxFileInfo, "系统文件不存在！");
//            if (!caxFileInfo.getExtension().equalsIgnoreCase(inputTypeStr)) {
//                throw new RuntimeException("输入文件格式和系统文件格式不匹配");
//            }
            fileName = caxFileInfo.getName();
            try {
                String filePath = createFilePath();
                Path destinationFile = Paths.get(filePath, fileName);
                Files.copy(Path.of(caxFileInfo.getPath()), destinationFile);
                sourceFilePath = destinationFile.toString();
            } catch (Exception e) {
                log.error("文件保存到服务器失败！", e);
                throw new BaseException("文件保存到服务器失败！");
            }
        } else {
            //本地文件
//            if (!FileUtils.isValidFileTypeBySuffix(inputTypeStr, file)) {
//                throw new RuntimeException("输入文件格式和上传文件不匹配");
//            }
            try {
                String filePath = createFilePath();
                fileName = file.getOriginalFilename();
                Path destinationFile = Paths.get(filePath, fileName);
                Files.copy(file.getInputStream(), destinationFile);
                sourceFilePath = destinationFile.toString();
            } catch (Exception e) {
                log.error("文件保存到服务器失败！", e);
                throw new BaseException("文件保存到服务器失败！");
            }
        }

        //保存转换记录
        LoginUser loginUser = LoginHelper.getLoginUser();
        Long deptId = loginUser.getDeptId();
        Long userId = loginUser.getUserId();
        CaxConvertInfo caxConvertInfo = new CaxConvertInfo();
        caxConvertInfo.setConvertType(convertTypeStr);
        caxConvertInfo.setInputType(inputTypeStr);
        caxConvertInfo.setOutputType(outputTypeStr);
        caxConvertInfo.setSourceFilePath(sourceFilePath);
        caxConvertInfo.setSourceFileName(fileName);
        //caxConvertInfo.setSource(ObjectUtils.isEmpty(sysClientVo) ? "" : sysClientVo.getClientKey());
        caxConvertInfo.setSource(fileSourceType);
        caxConvertInfo.setCreateBy(userId);
        caxConvertInfo.setUpdateBy(userId);
        caxConvertInfo.setCreateDept(deptId);

        boolean flag = false;

        // 获取数据库字典
        SysDictTypeVo cadConvertFlag = sysDictTypeService.selectDictTypeByType("cad_convert_flag");
        SysDictTypeVo caeConvertFlag = sysDictTypeService.selectDictTypeByType("cae_convert_flag");
        if (ObjectUtils.isEmpty(cadConvertFlag) || ObjectUtils.isEmpty(caeConvertFlag)) {
            throw new RuntimeException("转换配置异常");
        }
        // 输入CATProduct类型，文件格式校验，必须为zip格式
        if ("CATProduct".equals(inputTypeStr) && !FileUtils.isZipFile(sourceFilePath)) {
            throw new BaseException("CATProduct输入模型格式必须上传ZIP格式文件");
        }
        //文件转换
        try {
            if (CaxConvertType.CAD.equals(caxConvertType)) {
                flag = CaxFileConvertUtil.cadConvert(sourceFilePath, inputTypeStr, outputTypeStr, cadConvertFlag.getRemark());
            } else if (CaxConvertType.CAE_INPUT.equals(caxConvertType)) {
                flag = CaxFileConvertUtil.caeInputConvert(sourceFilePath, outputTypeStr, caeConvertFlag.getRemark());
            } else if (CaxConvertType.CAE_OUTPUT.equals(caxConvertType)) {
                flag = CaxFileConvertUtil.caeOutputConvert(sourceFilePath, outputTypeStr, caeConvertFlag.getRemark());
            }
        } catch (Exception e) {
            log.error("文件格式转换失败！", e);
            throw new BaseException("文件格式转换失败！");
        }
        BizAssertUtil.notNull(fileName, "fileName is null");
        String targetFileName;
        String targetFilePath;
        List<String> caeGeneralType = new ArrayList<>();
        caeGeneralType.add("vtk");
        caeGeneralType.add("gmesh");

        if (caeGeneralType.contains(outputTypeStr)) {
            String directoryPath = StringUtils.getDirectoryPath(sourceFilePath);
            targetFileName = StringUtils.extractFileName(sourceFilePath) + ".zip";
            targetFilePath = directoryPath + "/" + targetFileName;
        } else if ("CATProduct".equals(outputTypeStr) || "Sldasm".equals(outputTypeStr)) {
            String directoryPath = StringUtils.getDirectoryPath(sourceFilePath);
            targetFileName = StringUtils.extractFileName(sourceFilePath) + ".zip";
            targetFilePath = directoryPath + "/" + targetFileName;
        } else if ("CATPart".equals(outputTypeStr)) {
            String directoryPath = StringUtils.getDirectoryPath(sourceFilePath);
            targetFileName = StringUtils.extractFileName(sourceFilePath) + "." + outputTypeStr;
            targetFilePath = directoryPath + "/" + targetFileName;
        } else if ("Parasolid".equals(outputTypeStr)) {
            String directoryPath = StringUtils.getDirectoryPath(sourceFilePath);
            targetFileName = StringUtils.extractFileName(sourceFilePath) + ".x_t";
            targetFilePath = directoryPath + "/" + targetFileName;
        } else if ("HDF5".equals(outputTypeStr)) {
            String directoryPath = StringUtils.getDirectoryPath(sourceFilePath);
            targetFileName = StringUtils.extractFileName(sourceFilePath) + ".h5";
            targetFilePath = directoryPath + "/" + targetFileName;
        } else {
            targetFileName = FileUtils.changeFileExtension(fileName, outputTypeStr.toLowerCase());
            targetFilePath = FileUtils.changeFileExtension(sourceFilePath, outputTypeStr.toLowerCase());
        }
        caxConvertInfo.setTargetFileName(targetFileName);
        caxConvertInfo.setTargetFilePath(targetFilePath);
        if (flag) {
            File targetFile = new File(targetFilePath);
            long fileSize = targetFile.length() / 1024;
            caxConvertInfo.setTargetFileSize(Long.toString(fileSize));
        }
        //读取转换日志
        String logFilePath = FileUtils.changeFileExtension(sourceFilePath, "log");
        File logFile = new File(logFilePath);
        if (!logFile.exists()) {
            log.error("日志文件不存在！logFilePath：{}", logFilePath);
        }
        try {
            // 读取所有行到List<String>
            List<String> allLines = Files.readAllLines(Paths.get(logFilePath));
            // 将List<String>转换为单个字符串
            String content = String.join(System.lineSeparator(), allLines);
            caxConvertInfo.setConvertLog(content);
        } catch (Exception e) {
            log.error("读取日志文件失败！", e);
        }
        String status = flag ? CaxConvertStatus.SUCCESS.getCode() : CaxConvertStatus.FAILURE.getCode();
        caxConvertInfo.setStatus(status);
        caxConvertInfoMapper.insert(caxConvertInfo);

        if (flag && CaxConvertType.CAD.equals(caxConvertType)) {
            // 装配件处理（涉及上传压缩文件）
            if ("CATProduct".equals(inputTypeStr) || "Sldasm".equals(inputTypeStr)) {
                String directoryPath = StringUtils.getDirectoryPath(sourceFilePath);
                String fileName2 = StringUtils.extractFileName(sourceFilePath);
                sourceFilePath = directoryPath + "/" + fileName2 + "/" + fileName2 + "." + inputTypeStr;
            }
            // 处理targetFilePath
            if ("CATProduct".equals(outputTypeStr) || "Sldasm".equals(outputTypeStr)) {
                String directoryPath = StringUtils.getDirectoryPath(sourceFilePath);
                String fileName2 = StringUtils.extractFileName(sourceFilePath);
                String outputFilePath2 = directoryPath + "/" + fileName2;
                String newExtension = "CATProduct".equals(outputTypeStr) ? "CATProduct" : "sldasm";
                targetFilePath = outputFilePath2 + "/" + fileName2 + "." + newExtension;
            }
            //转换质量检查
            iCaxQualityCheckerService.check(caxConvertInfo.getId(), sourceFilePath, targetFilePath);
        }

        CaxConvertInfoVo vo = new CaxConvertInfoVo();
        BeanUtils.copyProperties(caxConvertInfo, vo);
        return vo;
    }

    /**
     * 创建文件上传路径
     *
     * @return 文件上传路径
     * @throws IOException 异常
     */
    public String createFilePath() throws IOException {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        String currentDate = sdf.format(new Date());
        String filePath = UPLOAD_PATH + currentDate + "/" + IdUtil.simpleUUID() + "/";
        // 创建目标目录如果它不存在
        Files.createDirectories(Paths.get(filePath));
        return filePath;
    }

    @Override
    public CaxConvertInfoVo queryById(Long id) {
        return caxConvertInfoMapper.selectVoById(id);
    }

    @Override
    public TableDataInfo<CaxConvertInfoVo> queryPageList(CaxConvertInfoBo bo) {
        bo.setEndCreateTime(DateUtils.toOneDayEndTime(bo.getEndCreateTime()));
        PageQuery pageQuery = new PageQuery();
        pageQuery.setPageNum(bo.getPageNum());
        pageQuery.setPageSize(bo.getPageSize());
        LambdaQueryWrapper<CaxConvertInfo> lqw = this.buildQueryWrapper(bo);
        Page<CaxConvertInfoVo> result = caxConvertInfoMapper.selectVoPage(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    private LambdaQueryWrapper<CaxConvertInfo> buildQueryWrapper(CaxConvertInfoBo bo) {
        LambdaQueryWrapper<CaxConvertInfo> lqw = Wrappers.lambdaQuery();
        lqw.eq(StringUtils.isNotBlank(bo.getConvertType()), CaxConvertInfo::getConvertType, bo.getConvertType());
        lqw.eq(StringUtils.isNotBlank(bo.getInputType()), CaxConvertInfo::getInputType, bo.getInputType());
        lqw.eq(StringUtils.isNotBlank(bo.getOutputType()), CaxConvertInfo::getOutputType, bo.getOutputType());
        lqw.eq(StringUtils.isNotBlank(bo.getSource()), CaxConvertInfo::getSource, bo.getSource());
        lqw.eq(StringUtils.isNotBlank(bo.getStatus()), CaxConvertInfo::getStatus, bo.getStatus());
        lqw.like(StringUtils.isNotBlank(bo.getSourceFileName()), CaxConvertInfo::getSourceFileName, bo.getSourceFileName());
        lqw.between(ObjectUtils.isNotEmpty(bo.getBeginCreateTime()) && ObjectUtils.isNotEmpty(bo.getEndCreateTime()),
            CaxConvertInfo::getCreateTime, bo.getBeginCreateTime(), bo.getEndCreateTime());
        lqw.orderByDesc(CaxConvertInfo::getCreateTime);
        return lqw;
    }

    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids) {
        return caxConvertInfoMapper.deleteBatchIds(ids) > 0;
    }

    @Override
    public void downloadSource(HttpServletResponse response, Long id) throws IOException {
        CaxConvertInfo caxConvertInfo = caxConvertInfoMapper.selectById(id);
        FileUtils.downloadFile(response, caxConvertInfo.getSourceFilePath(), caxConvertInfo.getSourceFileName());
    }

    @Override
    public void downloadTarget(HttpServletResponse response, Long id) throws IOException {
        CaxConvertInfo caxConvertInfo = caxConvertInfoMapper.selectById(id);
        if (caxConvertInfo.getStatus().equals(CaxConvertStatus.IN_PROGRESS.getCode())) {
            throw new RuntimeException("转换中数据，不能下载");
        } else if (caxConvertInfo.getStatus().equals(CaxConvertStatus.FAILURE.getCode())) {
            throw new RuntimeException("转换失败数据，不能下载");
        } else if (!caxConvertInfo.getStatus().equals(CaxConvertStatus.SUCCESS.getCode())) {
            throw new RuntimeException("转换数据状态异常，不能下载");
        }
        FileUtils.downloadFile(response, caxConvertInfo.getTargetFilePath(), caxConvertInfo.getTargetFileName());
    }

    @Override
    public void export(HttpServletResponse response, CaxConvertInfoBo bo) {
        bo.setEndCreateTime(DateUtils.toOneDayEndTime(bo.getEndCreateTime()));
        List<CaxConvertInfoExportVo> exportVoList = caxConvertInfoMapper.selectVoExportList(bo);

        if (CollectionUtils.isEmpty(exportVoList)) {
            throw new BaseException("没有需要导出的数据！");
        }

        exportVoList.forEach(vo -> vo.setStatus(CaxConvertStatus.getDescByValue(vo.getStatus())));

        // 封装导出的data
        Map<String, Object> data = new HashMap<>();
        String fileName = "文件转换记录清单";
        data.put(fileName, exportVoList);
        ExcelUtil.exportWithOutTemplateMultiList(data, fileName, CaxConvertInfoExportVo.class, response);
    }

    @Override
    public CaxConvertStatisticVo convertStatistic() {
        CaxConvertStatisticVo result = new CaxConvertStatisticVo();

        //转换量统计
        Long totalCount = caxConvertInfoMapper.selectCount(new LambdaQueryWrapper<>());
        result.setTotalCount(totalCount);

        //CAD转换量统计
        Long cadCount = caxConvertInfoMapper.selectCount(new LambdaQueryWrapper<CaxConvertInfo>().eq(CaxConvertInfo::getConvertType, CaxConvertType.CAD.toString()));
        result.setCadCount(cadCount);

        //CAE输入转换量统计
        Long caeInputCount = caxConvertInfoMapper.selectCount(new LambdaQueryWrapper<CaxConvertInfo>().eq(CaxConvertInfo::getConvertType, CaxConvertType.CAE_INPUT.toString()));
        result.setCaeInputCount(caeInputCount);

        //CAE输出转换
        Long caeOutputCount = caxConvertInfoMapper.selectCount(new LambdaQueryWrapper<CaxConvertInfo>().eq(CaxConvertInfo::getConvertType, CaxConvertType.CAE_OUTPUT.toString()));
        result.setCaeOutputCount(caeOutputCount);

        //文件统计
        Long fileCount = caxFileInfoMapper.selectCount(new LambdaQueryWrapper<>());
        result.setFileCount(fileCount);

        //输入模型格式TOP5
        List<CaxConvertStatisticItem> inputTypeTopCountList = caxConvertInfoMapper.selectInputTypeTopCountList();
        inputTypeTopCountList = inputTypeTopCountList.stream().sorted().toList();
        result.setInputTypeTopList(inputTypeTopCountList);

        //输出模型格式TOP5
        List<CaxConvertStatisticItem> outputTypeTopCountList = caxConvertInfoMapper.selectOutputTypeTopCountList();
        outputTypeTopCountList = outputTypeTopCountList.stream().sorted().toList();
        result.setOutputTypeTopList(outputTypeTopCountList);

        List<CaxConvertStatisticItem> inputTypeGroupCountList = caxConvertInfoMapper.selectInputTypeGroupCountList();
        List<CaxConvertStatisticItem> outputTypeGroupCountList = caxConvertInfoMapper.selectOutputTypeGroupCountList();
        //CAD转换输入模型占比
        List<CaxConvertStatisticItem> cadInputTypeRatiolist = inputTypeGroupCountList.stream().filter(i -> CaxConvertType.CAD.toString().equals(i.getConvertType())).toList();
        cadInputTypeRatiolist.forEach(i -> {
            i.setRatio(String.valueOf(String.format("%.1f", i.getCount().doubleValue() / cadCount * 100)));
        });
        result.setCadInputTypeRatioList(cadInputTypeRatiolist);

        //CAD转换输出模型占比
        List<CaxConvertStatisticItem> cadOutputTypeRatiolist = outputTypeGroupCountList.stream().filter(i -> CaxConvertType.CAD.toString().equals(i.getConvertType())).toList();
        cadOutputTypeRatiolist.forEach(i -> {
            i.setRatio(String.valueOf(String.format("%.1f", i.getCount().doubleValue() / cadCount * 100)));
        });
        result.setCadOutputTypeRatioList(cadOutputTypeRatiolist);

        //CAE输出转换输入模型占比
        List<CaxConvertStatisticItem> caeOutputInputTypeRatiolist = inputTypeGroupCountList.stream().filter(i -> CaxConvertType.CAE_OUTPUT.toString().equals(i.getConvertType())).toList();
        caeOutputInputTypeRatiolist.forEach(i -> {
            i.setRatio(String.valueOf(String.format("%.1f", i.getCount().doubleValue() / caeOutputCount * 100)));
        });
        result.setCaeOutputInputTypeRatioList(caeOutputInputTypeRatiolist);

        //CAE输出转换输出模型占比
        List<CaxConvertStatisticItem> caeOutputOutputTypeRatiolist = outputTypeGroupCountList.stream().filter(i -> CaxConvertType.CAE_OUTPUT.toString().equals(i.getConvertType())).toList();
        caeOutputOutputTypeRatiolist.forEach(i -> {
            i.setRatio(String.valueOf(String.format("%.1f", i.getCount().doubleValue() / caeOutputCount * 100)));
        });
        result.setCaeOutputOutputTypeRatioList(caeOutputOutputTypeRatiolist);

        //CAE输入转换输入模型占比
        List<CaxConvertStatisticItem> caeInputInputTypeRatiolist = inputTypeGroupCountList.stream().filter(i -> CaxConvertType.CAE_INPUT.toString().equals(i.getConvertType())).toList();
        caeInputInputTypeRatiolist.forEach(i -> {
            i.setRatio(String.valueOf(String.format("%.1f", i.getCount().doubleValue() / caeInputCount * 100)));
        });
        result.setCaeInputInputTypeRatioList(caeInputInputTypeRatiolist);

        //CAE输入转换输出模型占比
        List<CaxConvertStatisticItem> caeInputOutputTypeRatiolist = outputTypeGroupCountList.stream().filter(i -> CaxConvertType.CAE_INPUT.toString().equals(i.getConvertType())).toList();
        caeInputOutputTypeRatiolist.forEach(i -> {
            i.setRatio(String.valueOf(String.format("%.1f", i.getCount().doubleValue() / caeInputCount * 100)));
        });
        result.setCaeInputOutputTypeRatioList(caeInputOutputTypeRatiolist);

        return result;
    }

    @Override
    public LinkedHashMap<Object, List<CaxConvertStatisticItem>> convertStatisticByDate(String startTime, String endTime) {
        LinkedHashMap<Object, List<CaxConvertStatisticItem>> result = new LinkedHashMap<>();
        Date startDate = null;
        Date endDate = null;
        try {
            startDate = DateUtils.parseDate(startTime, "yyyy-MM-dd");
            endDate = DateUtils.parseDate(endTime, "yyyy-MM-dd");
        } catch (Exception e) {
            log.error("日期格式转换异常!", e);
            throw new BaseException("参数格式错误!");
        }

        //查询数据
        endTime = DateUtils.parseDateToStr("yyyy-MM-dd", DateUtils.addDays(endDate, 1));
        List<CaxConvertStatisticItem> countLimitDateList = caxConvertInfoMapper.selectCountLimitDateList(startTime, endTime);
        Date tempDate = startDate;
        while (endDate.compareTo(tempDate) >= 0) {
            String tempDateStr = DateUtils.parseDateToStr("yyyy-MM-dd", tempDate);
            List<CaxConvertStatisticItem> items = countLimitDateList.stream().filter(i -> i.getDate().equals(tempDateStr)).toList();
            items = items.stream().sorted().toList();
            items = new ArrayList<>(items);
            //设置默认数据
            if (items.size() < CaxConvertType.values().length) {
                if (items.stream().noneMatch(i -> CaxConvertType.CAD.toString().equals(i.getConvertType()))) {
                    CaxConvertStatisticItem item = new CaxConvertStatisticItem();
                    item.setConvertType(CaxConvertType.CAD.toString());
                    item.setCount(0L);
                    item.setDate(tempDateStr);
                    items.add(item);
                }
                if (items.stream().noneMatch(i -> CaxConvertType.CAE_INPUT.toString().equals(i.getConvertType()))) {
                    CaxConvertStatisticItem item = new CaxConvertStatisticItem();
                    item.setConvertType(CaxConvertType.CAE_INPUT.toString());
                    item.setCount(0L);
                    item.setDate(tempDateStr);
                    items.add(item);
                }
                if (items.stream().noneMatch(i -> CaxConvertType.CAE_OUTPUT.toString().equals(i.getConvertType()))) {
                    CaxConvertStatisticItem item = new CaxConvertStatisticItem();
                    item.setConvertType(CaxConvertType.CAE_OUTPUT.toString());
                    item.setCount(0L);
                    item.setDate(tempDateStr);
                    items.add(item);
                }
            }
            result.put(tempDateStr, items);
            tempDate = DateUtils.addDays(tempDate, 1);
        }
        return result;
    }

    @Override
    public void downloadByPath(HttpServletResponse response, String filePath) throws IOException {
        File file = new File(filePath);
        if (file.exists()) {
            FileUtils.downloadFile(response, filePath, StringUtils.extractFileNameAndSuffix(filePath));
        }
    }
}
